﻿namespace Resharper.Abstractions.CodeDom
{
  using System.Collections.Generic;
  using JetBrains.Annotations;
  using JetBrains.ReSharper.Psi;
  using JetBrains.ReSharper.Psi.Util;

  /// <summary>Defines the <see cref="DeclaredElement"/> class.</summary>
  public class DeclaredElement
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="InternalDeclaredElement"/> class.</summary>
    /// <param name="declaredElement">The declared element.</param>
    internal DeclaredElement(IDeclaredElement declaredElement)
    {
      this.InternalDeclaredElement = declaredElement;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the name.
    /// </summary>
    [NotNull]
    public string Name
    {
      get
      {
        return this.InternalDeclaredElement.ShortName;
      }
    }

    /// <summary>
    /// Gets the parameters.
    /// </summary>
    public IEnumerable<ParameterElement> Parameters
    {
      get
      {
        var parametersOwner = this.InternalDeclaredElement as JetBrains.ReSharper.Psi.IParametersOwner;
        if (parametersOwner == null)
        {
          yield break;
        }

        foreach (var parameter in parametersOwner.Parameters)
        {
          yield return new ParameterElement(parameter);
        }
      }
    }

    /// <summary>
    /// Gets the name.
    /// </summary>
    [NotNull]
    public Type Type
    {
      get
      {
        return new Type(this.InternalDeclaredElement.Type(), this.InternalDeclaredElement.PresentationLanguage);
      }
    }

    /// <summary>
    /// Gets the type of the containing.
    /// </summary>
    [CanBeNull]
    public string ContainingTypeName
    {
      get
      {
        var typeMember = this.InternalDeclaredElement as ITypeMember;
        if (typeMember == null)
        {
          return null;
        }

        var containingType = typeMember.GetContainingType();
        if (containingType == null)
        {
          return null;
        }

        return containingType.GetClrName().FullName;
      }
    }

    /// <summary>
    /// Gets or sets the internal declared element.
    /// </summary>
    /// <value>The internal declared element.</value>
    internal IDeclaredElement InternalDeclaredElement { get; private set; }

    #endregion
  }
}